package cn.turboinfo.fuyang.api.domain.mini.usecase.order;

import cn.turboinfo.fuyang.api.domain.common.service.product.ProductService;
import cn.turboinfo.fuyang.api.domain.common.service.product.ProductSkuService;
import cn.turboinfo.fuyang.api.domain.common.service.spec.SpecService;
import cn.turboinfo.fuyang.api.domain.common.service.spec.SpecSetRelService;
import cn.turboinfo.fuyang.api.domain.common.usecase.AbstractUseCase;
import cn.turboinfo.fuyang.api.entity.common.enumeration.common.EntityObjectType;
import cn.turboinfo.fuyang.api.entity.common.pojo.product.Product;
import cn.turboinfo.fuyang.api.entity.common.pojo.product.ProductSku;
import cn.turboinfo.fuyang.api.entity.common.pojo.spec.Spec;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 下单界面可选的sku列表
 *
 * @author sunshow
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class MiniAvailableProductSkuForOrderUseCase extends AbstractUseCase<MiniAvailableProductSkuForOrderUseCase.InputData, MiniAvailableProductSkuForOrderUseCase.OutputData> {

    private final SpecService specService;

    private final ProductSkuService productSkuService;

    private final ProductService productService;
    private final SpecSetRelService specSetRelService;

    @Override
    protected OutputData doAction(InputData inputData) {
        Long productId = inputData.getProductId();

        Product product = productService.getByIdEnsure(productId);

        // 获取产品SKU列表
        List<ProductSku> productSkuList = productSkuService.findSkuByProductId(productId);

        //查询属性组
        specSetRelService.getByRelObject(product.getId(), EntityObjectType.PRODUCT)
                .ifPresent(specSetRel -> product.setSpecSetId(specSetRel.getSpecSetId()));

        List<Spec> specTree = specService.findBySpecSetIdWithHierarchy(product.getSpecSetId());

        // 返回可选时段
        // -隔开, 如果只有一段则只要选开始时间
        List<String> availableTimeList = new ArrayList<>();
        // 暂时默认早8点到晚8点, 每半小时一个时段
        for (int i = 8; i <= 20; i++) {
            availableTimeList.add(String.format("%02d:00", i));
            availableTimeList.add(String.format("%02d:30", i));
        }

        // 返回可选日期
        List<LocalDate> availableDateList = new ArrayList<>();
        // 暂时默认最近七天
        LocalDateTime now = LocalDateTime.now();
        LocalDate firstDay = now.toLocalDate();
        if (now.getHour() > 20) {
            firstDay = firstDay.plusDays(1);
        }
        for (int i = 0; i < 7; i++) {
            availableDateList.add(firstDay.plusDays(i));
        }

        return OutputData.builder()
                .productSkuList(productSkuList)
                .specTree(specTree)
                .availableDateList(availableDateList)
                .availableTimeList(availableTimeList)
                .build();
    }

    @EqualsAndHashCode(callSuper = true)
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class InputData extends AbstractUseCase.InputData {

        @NotNull(message = "产品不能为空")
        private Long productId;

    }

    @Getter
    @Setter
    @Builder
    public static class OutputData extends AbstractUseCase.OutputData {

        /**
         * 可下单的产品SKU列表
         */
        private List<ProductSku> productSkuList;

        /**
         * 树型规格层级
         */
        private List<Spec> specTree;

        /**
         * 可预约时间段
         */
        private List<String> availableTimeList;

        /**
         * 可预约日期
         */
        private List<LocalDate> availableDateList;
    }
}
